在本系列的第一部分中,我們探討了 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.")
腳本的工作原理如下:
- 日誌檔案管理:Tutor 將所有日誌保存在 /root/.local/share/tutor/data/lms/logs/all.log 檔案中。該檔案包含MySQL、LMS、CMS、Caddy、Celery 和其他服務。此腳本使用指標 /root/.local/share/tutor/data/lms/logs/processed.log 檔案來追蹤最後處理的行。這確保每個日誌僅處理一次。
- 錯誤過濾:如前所述,我們僅將錯誤日誌傳送到 AppSignal。
- 資料解析和格式化:解析每個錯誤日誌以提取關鍵訊息,例如時間戳記和錯誤訊息。該腳本將此資料格式化為適合傳輸的 JSON 結構。
- 日誌傳輸:使用 HTTP POST 要求將格式化的日誌資料傳送到 AppSignal。
重要提示:請確保您沒有向端點發送任何個人識別資訊。
現在運行此腳本,它應該將錯誤日誌移至 AppSignal:
您也可以建立一個新的觸發器,以便在發生錯誤等特定事件時立即通知您:
使用 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。
回到 AppSignal 中的儀表板,我們應該在 效能 部分看到 Celery 和 Redis 報告,其中 background 作為命名空間。
對於Redis查詢,您可以點選慢速查詢:
實用監控:使用 AppSignal 增強 Open edX
在本節中,我們將重新審視本系列第一部分中概述的初始問題,並應用實用的 AppSignal 監控解決方案,以確保我們的 Open edX 平台保持強大且可靠。這是一個細分。
網站效能改進
我們首先評估網站的整體表現。在效能部分的問題清單下,我們可以看到所有訪問過的URL的關鍵指標:
- 回應時間:透過測量處理和回應請求所需的時間來直接反映使用者體驗。影響這一點的因素包括資料庫查詢和中間件操作。
- 吞吐量:表示在給定時間範圍內處理的請求數量。
- 平均回應時間:提供對特定端點的所有請求的平均回應時間。任何超過 1 秒的平均反應時間都是一個潛在問題,並突出顯示需要優化的區域。
- 90% 回應時間:例如,GET store/ 的 90% 回應時間為 7 毫秒,表示 90% 的請求在 7 毫秒或更短時間內完成。
現在讓我們根據平均值對所有操作進行排序。任何超過 1 秒的項目都應被視為危險信號:
如我們所見,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中,以在有新事件時追蹤和增加登入和註冊的數量。
現在讓我們登入 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中文網其他相關文章!

Python和C 各有優勢,選擇應基於項目需求。 1)Python適合快速開發和數據處理,因其簡潔語法和動態類型。 2)C 適用於高性能和系統編程,因其靜態類型和手動內存管理。

選擇Python還是C 取決於項目需求:1)如果需要快速開發、數據處理和原型設計,選擇Python;2)如果需要高性能、低延遲和接近硬件的控制,選擇C 。

通過每天投入2小時的Python學習,可以有效提升編程技能。 1.學習新知識:閱讀文檔或觀看教程。 2.實踐:編寫代碼和完成練習。 3.複習:鞏固所學內容。 4.項目實踐:應用所學於實際項目中。這樣的結構化學習計劃能幫助你係統掌握Python並實現職業目標。

在兩小時內高效學習Python的方法包括:1.回顧基礎知識,確保熟悉Python的安裝和基本語法;2.理解Python的核心概念,如變量、列表、函數等;3.通過使用示例掌握基本和高級用法;4.學習常見錯誤與調試技巧;5.應用性能優化與最佳實踐,如使用列表推導式和遵循PEP8風格指南。

Python適合初學者和數據科學,C 適用於系統編程和遊戲開發。 1.Python簡潔易用,適用於數據科學和Web開發。 2.C 提供高性能和控制力,適用於遊戲開發和系統編程。選擇應基於項目需求和個人興趣。

Python更適合數據科學和快速開發,C 更適合高性能和系統編程。 1.Python語法簡潔,易於學習,適用於數據處理和科學計算。 2.C 語法複雜,但性能優越,常用於遊戲開發和系統編程。

每天投入兩小時學習Python是可行的。 1.學習新知識:用一小時學習新概念,如列表和字典。 2.實踐和練習:用一小時進行編程練習,如編寫小程序。通過合理規劃和堅持不懈,你可以在短時間內掌握Python的核心概念。

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

Dreamweaver CS6
視覺化網頁開發工具