Observability:將 OpenTelemetry 添加到你的 Flask 應用程序

作者:來自 Elastic?jessgarson

待辦事項列表可以幫助管理與假期計劃相關的所有購物和任務。使用 Flask,你可以輕松創建待辦事項列表應用程序,并使用 Elastic 作為遙測后端,通過 OpenTelemetry 對其進行監控。

Flask 是一個輕量級的 Python Web 框架,可讓你輕松創建應用程序。OpenTelemetry 是一個開源的、與供應商無關的可觀察性框架,它提供跨不同服務和平臺的統一監控功能,允許與各種后端系統無縫集成。

這篇文章將引導你使用 OpenTelemetry Python 的 Elastic Distribution 來監控 Flask 中內置的待辦事項列表應用程序。本文中概述的示例的完整代碼可以在此處找到。

如何將 Elastic 連接到 OpenTelemetry?

OpenTelemetry 的一大優點是它可以靈活地與你的應用程序集成。使用 Elastic 作為遙測后端。你有幾個選擇;你可以使用 OpenTelemetry 收集器(官方 OpenTelmetry 語言客戶端)連接到 APM(AWS Lambda 收集器導出器)。我們的文檔可讓你詳細了解將 OpenTelemetry 連接到 Elastic 的選項。

你將使用 OpenTelemetry Python 的 Elastic Distribution 作為本文中的示例。此庫是 OpenTelemetry Python 的一個版本,具有附加功能并支持將 OpenTelemetry 與 Elastic 集成。需要注意的是,此包目前處于預覽階段,不應在生產環境中使用。

使用 Flask 創建待辦事項列表應用程序

在監控應用程序之前,你必須先創建它。本文將指導你創建一個簡單的待辦事項列表應用程序來幫助你跟蹤任務。完成應用程序后,它將如下所示:

開始之前,你需要創建一個虛擬環境。創建虛擬環境后,你需要安裝所需的軟件包。

pip install Flask Flask-SQLAlchemy

安裝所需的軟件包后,你必須導入必要的軟件包和方法,配置 Flask 應用程序,并使用 SQLalachemy 設置 SQLite 數據庫。之后,你將定義一個數據庫模型來存儲和列出任務項。你還需要初始化應用程序以使用 SQLalcamey,并通過創建所需的表來初始化數據庫。

from flask import Flask, request, render_template_string, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import Mapped, mapped_columnapp = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///tasks.db"
db = SQLAlchemy()# Define a database model named Task for storing task data
class Task(db.Model):id: Mapped[int] = mapped_column(db.Integer, primary_key=True)description: Mapped[str] = mapped_column(db.String(256), nullable=False)# Initialize SQLAlchemy with the configured Flask application
db.init_app(app)# Initialize the database within the application context
with app.app_context():db.create_all()  # Creates all tables

你現在可以設置 HTML 模板來創建待辦事項列表應用程序的前端,包括用于添加任務的內聯 CSS 和表單內容。你還將定義用于列出現有任務和刪除任務的其他功能。

HOME_HTML = """
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>To-Do List</title><style>body {font-family: Arial, sans-serif;background-color: #f4f4f9;margin: 40px auto;padding: 20px;max-width: 600px;box-shadow: 0 0 10px rgba(0,0,0,0.1);}h1 {color: #333;}form {margin-bottom: 20px;}input[type="text"] {padding: 10px;width: calc(100% - 22px);margin-bottom: 10px;}input[type="submit"] {background-color: #5cb85c;border: none;color: white;padding: 10px 20px;text-transform: uppercase;letter-spacing: 0.05em;cursor: pointer;}ul {list-style-type: none;padding: 0;}li {position: relative;padding: 8px;background-color: #fff;border-bottom: 1px solid #ddd;}.delete-button {position: absolute;right: 10px;top: 10px;background-color: #ff6347;color: white;border: none;padding: 5px 10px;border-radius: 5px;cursor: pointer;}</style>
</head>
<body><h1>To-Do List</h1><form action="/add" method="post"><input type="text" name="task" placeholder="Add new task"><input type="submit" value="Add Task"></form><ul>{% for task in tasks %}<li>{{ task.description }} <button class="delete-button" onclick="location.href='/delete/{{ task.id }}'">Delete</button></li>{% endfor %}</ul>
</body>
</html>
"""

現在,你可以創建路由,以便在加載時在應用程序上顯示待辦事項列表任務、添加新任務和刪除任務。

/ 路由允許你定義當有人訪問應用程序主頁時返回哪些數據;在這種情況下,你從數據庫輸入的所有待辦事項列表任務都將顯示在屏幕上。

對于添加新任務,當你在應用程序上填寫表單以添加和提交新任務時,/add 路由會將此新任務保存在數據庫中。保存任務后,它會將你送回主頁,以便他們可以看到添加了新任務的列表。

你還將為 /delete 定義一個路由,它描述了當你刪除任務時會發生什么(在本例中,當你單擊任務旁邊的刪除按鈕時)。然后,應用程序會從數據庫中刪除該任務。

最后,你將添加邏輯來運行應用程序。

# Define route for the home page to display tasks
@app.route("/", methods=["GET"])
def home():tasks = Task.query.all()  # Retrieve all tasks from the databasereturn render_template_string(HOME_HTML, tasks=tasks)  # Render the homepage with tasks listed# Define route to add new tasks from the form submission
@app.route("/add", methods=["POST"])
def add():task_description = request.form["task"]  # Extract task description from form datanew_task = Task(description=task_description)  # Create new Task instancedb.session.add(new_task)  # Add new task to database sessiondb.session.commit()  # Commit changes to the databasereturn redirect(url_for("home"))  # Redirect to the home page# Define route to delete tasks based on task ID
@app.route("/delete/<int:task_id>", methods=["GET"])
def delete(task_id: int):task_to_delete = Task.query.get(task_id)  # Get task by IDif task_to_delete:db.session.delete(task_to_delete)  # Remove task from the database sessiondb.session.commit()  # Commit the change to the databasereturn redirect(url_for("home"))  # Redirect to the home page# Check if the script is the main program and run the app
if __name__ == "__main__":app.run()  # Start the Flask application

要在本地運行你的應用程序,你可以在終端中運行以下命令。

flask run -p 5000

檢測應用程序

檢測是指向應用程序添加可觀察性功能以收集遙測數據,例如跟蹤、指標和日志。在數據中,你可以看到正在運行的依賴服務;例如,你可以看到正在構建的應用程序(在此示例中)使用 SQLite。你還可以跟蹤請求在分布式系統中跨度移動的各種服務,并查看有關在分布式系統中運行的進程的定量信息。

自動檢測與手動檢測

你有兩種檢測應用程序的選項:自動檢測手動檢測

自動檢測會修改應用程序類的字節碼以將監控代碼插入到應用程序中。使用自動檢測,你可以輕松監控應用程序,而無需擔心創建自定義監控。這是一種開始監控應用程序或向現有應用程序添加監控功能的好方法。

手動檢測允許你向應用程序添加自定義代碼段以收集和傳輸遙測數據。如果你正在尋找自定義或發現自動檢測僅涵蓋你需要的部分內容,則它很有用。

向你的待辦事項列表應用程序添加自動檢測

要向你的 Flask 應用程序添加自動檢測,你無需添加任何其他監控代碼。當你運行應用程序時,OpenTelemetry 將通過 Python 路徑自動添加所需的代碼。你可以按照以下步驟向你的應用程序添加自動檢測。

步驟 1:安裝所需的軟件包

首先,你需要安裝檢測所需的軟件包。

pip install elastic-opentelemetry opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-instrumentation-flask
opentelemetry-bootstrap --action=install

第 2 步:設置本地環境變量

現在,你可以設置環境變量以包含應用程序的服務名稱、API 密鑰和彈性主機端點。

export OTEL_RESOURCE_ATTRIBUTES=service.name=todo-list-app
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=ApiKey <your-api-key>"
export OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-elastic-url>

步驟 3:運行應用程序

要使用 OpenTelemetry 運行你的應用程序,你需要在終端中運行以下命令:

opentelemetry-instrument flask run -p 5000

此時,如果你查看 Kibana,其中顯示 “observability”? 緊接著?“services”,你應該會看到你的服務列為你在環境變量中設置的服務名稱。

如果你點擊 service 名稱,你應該會看到一個儀表板,其中包含待辦事項列表應用程序的可觀察性數據。下面的 “Transactions” 部分中的屏幕截圖顯示了你可以采取的操作,例如在使用 GET 方法加載應用程序時加載所有待辦事項列表項,以及使用 POST 方法將新項目添加到待辦事項列表中。

向你的待辦事項列表應用程序添加手動檢測

由于手動檢測允許你根據自己的喜好自定義檢測,因此你必須將自己的監控代碼添加到你的應用程序中才能啟動并運行。本節的完整代碼示例可在此處找到。

首先,你需要通過設置以下環境變量來更新你的服務名稱:

export OTEL_RESOURCE_ATTRIBUTES=service.name=mi-todo-list-app

現在你已經更新了 service 名稱,你需要更新導入語句以包含更多功能,用于監控應用程序、解析環境變量以及確保標頭格式正確。

import os
from flask import Flask, request, render_template_string, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import Mapped, mapped_column
from opentelemetry import trace, metrics
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter# Get environment variables
service_name = os.getenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=todo-flask-app").split("=")[-1]
otlp_endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
otlp_headers = os.getenv("OTEL_EXPORTER_OTLP_HEADERS")if not otlp_endpoint or not otlp_headers:raise ValueError("OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS must be set in environment variables")# Ensure headers are properly formatted for gRPC metadata
headers_dict = dict(item.split(":", 1) for item in otlp_headers.split(",") if ":" in item)

現在,你將需要配置你的應用程序以生成、批處理和發送跟蹤數據到 Elastic,從而深入了解你的應用程序的運行和性能。

# Configure tracing provider and exporter
resource = Resource(attributes={"service.name": service_name
})
trace.set_tracer_provider(TracerProvider(resource=resource))
tracer_provider = trace.get_tracer_provider()otlp_trace_exporter = OTLPSpanExporter(endpoint=otlp_endpoint,headers=headers_dict,
)
span_processor = BatchSpanProcessor(otlp_trace_exporter)
tracer_provider.add_span_processor(span_processor)

你現在可以設置用于捕獲遙測數據的框架。你需要創建跟蹤器、計量器和計數器。跟蹤器為分布式跟蹤創建跨度,幫助了解分布式系統的流程和性能問題。計量器和計數器捕獲操作指標(如計數請求)對于生產環境中的性能監控和警報至關重要。你的指標配置可確保這些指標得到適當批處理并發送到 Elastic 進行分析。

# Create a tracer
tracer = trace.get_tracer(__name__)# Configure metrics provider and exporter
otlp_metric_exporter = OTLPMetricExporter(endpoint=otlp_endpoint,headers=headers_dict,
)
metric_reader = PeriodicExportingMetricReader(otlp_metric_exporter)
meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(meter_provider)# Create a meter
meter = metrics.get_meter(__name__)
requests_counter = meter.create_counter(name="requests_count",description="Number of requests received",unit="1",
)

你將需要使用 Flask 和 SQLite 來獲取有關可觀察性后端(即 Elastic)中的這兩項服務的信息。

FlaskInstrumentor().instrument_app(app)
with app.app_context():SQLAlchemyInstrumentor().instrument(engine=db.engine)

現在,你可以為每個應用程序路由配備跟蹤和指標收集功能。這樣你就可以定義向每個路由(GET、POST 和 DELETE)添加哪些跟蹤和指標,從而讓你能夠了解運營績效,同時還可以收集有關用戶交互和系統效率的寶貴數據。

# Define route for the home page to display tasks
@app.route("/", methods=["GET"])
def home():with app.app_context():with tracer.start_as_current_span("home-request"):requests_counter.add(1, {"method": "GET", "endpoint": "/"})tasks = Task.query.all()  # Retrieve all tasks from the databasereturn render_template_string(HOME_HTML, tasks=tasks)  # Render the homepage with tasks listed# Define route to add new tasks from the form submission
@app.route("/add", methods=["POST"])
def add():with app.app_context():with tracer.start_as_current_span("add-task"):requests_counter.add(1, {"method": "POST", "endpoint": "/add"})task_description = request.form["task"]  # Extract task description from form datanew_task = Task(description=task_description)  # Create new Task instancedb.session.add(new_task)  # Add new task to database sessiondb.session.commit()  # Commit changes to the databasereturn redirect(url_for("home"))  # Redirect to the home page# Define route to delete tasks based on task ID
@app.route("/delete/<int:task_id>", methods=["GET"])
def delete(task_id: int):with app.app_context():with tracer.start_as_current_span("delete-task"):requests_counter.add(1, {"method": "GET", "endpoint": f"/delete/{task_id}"})task_to_delete = Task.query.get(task_id)  # Get task by IDif task_to_delete:db.session.delete(task_to_delete)  # Remove task from the database sessiondb.session.commit()  # Commit the change to the databasereturn redirect(url_for("home"))  # Redirect to the home page

由于你已將自定義監控代碼應用到你的應用程序中,因此你可以像第一次創建它時一樣在終端中運行。

flask run -p 5000

現在你應該可以在 “Services” 下看到你的數據,其方式與自動檢測中相同。

結論

由于 OpenTelemetry 的一大特色是其可定制性,因此這只是你如何使用 Elastic 作為 OpenTelemetry 后端的開始。下一步,請探索我們的 OpenTelemetry 演示應用程序,以了解如何在更實際的應用程序中運用 Elastic。你也可以將此應用程序部署到服務器。

此示例的完整代碼可在此處找到。如果你基于此博客構建了任何內容,或者你對我們的論壇和社區 Slack 頻道有疑問,請告訴我們。

原文:Dec 6th, 2024: [EN] Adding OpenTelemetry to Your Flask Application - Advent Calendar - Discuss the Elastic Stack

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65853.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65853.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65853.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Matplotlib顯示中文的方法

1 問題提出 使用圖1所示的代碼進行matplotlib繪圖時&#xff0c;因為其默認不支持中文&#xff0c;此時無法顯示正確內容&#xff0c;如圖2所示。 圖1 matplotlib繪圖繪圖代碼 圖2 matplotlib無法顯示中文 2 問題解決 2.1 設置全局字體 在圖1所示的代碼中&#xff0c;第13…

詳解opencv resize之INTER_LINEAR和INTER_AREA

一。先簡單介紹一下resize的用法 src&#xff1a;輸入圖&#xff0c; dst&#xff1a;輸出圖 dsize&#xff1a;輸出圖的寬高&#xff0c;如果dsize不為空&#xff08;即寬高都不是0&#xff09;&#xff0c;則以dsize為準進行resize。 fx, fy是放大縮小的比例&#xff0c;是…

UnityDemo-TheBrave-制作筆記

這是我跟著b站up主MStudio的視頻學習制作的&#xff0c;大體上沒有去做一些更新的東西&#xff0c;這里只是一個總的總結。在文章的最后&#xff0c;我會放上可以游玩該游戲的鏈接和exe可執行文件&#xff0c;不過沒有對游戲內容進行什么加工&#xff0c;只有基本的功能實現罷了…

使用LSTM預測股票收盤價

在金融數據預測中&#xff0c;LSTM&#xff08;長短期記憶網絡&#xff09;憑借其在時間序列數據建模中的優勢&#xff0c;成為了分析股票價格趨勢的熱門選擇。本篇博客將以完整的代碼實現為例&#xff0c;展示如何利用LSTM網絡對股票收盤價進行預測&#xff0c;并從數據處理到…

模擬SpringIOCAOP

一、IOC容器 Ioc負責創建&#xff0c;管理實例&#xff0c;向使用者提供實例&#xff0c;ioc就像一個工廠一樣&#xff0c;稱之為Bean工廠 1.1 Bean工廠的作用 先分析一下Bean工廠應具備的行為 1、需要一個獲取實例的方法&#xff0c;根據一個參數獲取對應的實例 getBean(…

預編譯SQL

預編譯SQL 預編譯SQL是指在數據庫應用程序中&#xff0c;SQL語句在執行之前已經通過某種機制&#xff08;如預編譯器&#xff09;進行了解析、優化和準備&#xff0c;使得實際執行時可以直接使用優化后的執行計劃&#xff0c;而不需要每次都重新解析和編譯。這么說可能有一些抽…

Centos9 + Docker 安裝 MySQL8.4.0 + 定時備份數據庫到本地

Centos9 + Docker 安裝 MySQL8.4.0 + 定時備份數據庫到本地 創建目錄,創建配置文件啟動容器命令定時備份MySQL執行腳本Linux每日定時任務命令文件內參數其他時間參數AT一次性定時任務創建目錄,創建配置文件 $ mkdir -p /opt/mysql/conf$ vim /opt/mysql/conf/my.cnf[mysql] #…

軟件測試預備知識⑥—搭建Web服務器

在軟件測試的廣闊領域中&#xff0c;搭建Web服務器是一項極為關鍵的技能。它不僅有助于模擬真實的應用環境&#xff0c;方便我們對Web應用進行全面且深入的測試&#xff0c;還能讓測試人員更好地掌控測試場景&#xff0c;提升測試效率與質量。接下來&#xff0c;讓我們一同深入…

計算機視覺算法實戰——打電話行為檢測

?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連 ? ?個人主頁歡迎您的訪問 ?期待您的三連? ??????? ??????????????? ?????? ? 1. 引言?? 隨著智能手機的普及&#xff0c;打電話行為檢測成為了計算機視…

事務的隔離級別和MDL

文章目錄 說明不同隔離級別可能發生的現象關鍵現象解釋MDL&#xff08;元數據鎖&#xff0c;Metadata Lock&#xff09;MDL 的作用MDL 的工作原理MDL 鎖的常見場景如何避免 MDL 阻塞 說明 本文章由大模型對話整理而來&#xff0c;如果有錯誤之處&#xff0c;請在評論區留言指正…

Linux第二課:LinuxC高級 學習記錄day01

0、大綱 0.1、Linux 軟件安裝&#xff0c;用戶管理&#xff0c;進程管理&#xff0c;shell 命令&#xff0c;硬鏈接和軟連接&#xff0c;解壓和壓縮&#xff0c;功能性語句&#xff0c;結構性語句&#xff0c;分文件&#xff0c;make工具&#xff0c;shell腳本 0.2、C高級 …

單片機存儲與計算機存儲:從微小到龐大的數據世界

單片機存儲與計算機存儲&#xff1a;從微小到龐大的數據世界 在現代電子設備中&#xff0c;存儲是至關重要的組成部分。無論是小巧的單片機&#xff0c;還是功能強大的計算機&#xff0c;存儲都扮演著不可或缺的角色。然而&#xff0c;單片機和計算機的存儲架構卻有著天壤之別…

ISP流程--去馬賽克詳解

前言 本期我們將深入討論ISP流程中的去馬賽克處理。我們熟知&#xff0c;彩色圖像由一個個像元組成&#xff0c;每個像元又由紅、綠、藍&#xff08;RGB&#xff09;三通道構成。而相機傳感器只能感知光的強度&#xff0c;無法直接感知光譜信息&#xff0c;即只有亮暗而沒有顏色…

阿里云-通義靈碼:在 PyCharm 中的強大助力(下)

目錄 六.通義靈碼在 PyCharm 中的優勢與不足 1.優勢 (1).提高開發效率 (2).提升代碼質量 (3).易于使用 (4).不斷學習和改進 2.不足 (1).依賴網絡 (2).準確性有待提高 (3).局限性 七.未來發展展望 1.提高準確性和可靠性 2.與其他工具的集成 3.智能化程度的提升 八…

開源項目stable-diffusion-webui部署及生成照片

參考鏈接 https://www.freedidi.com/13133.html 基礎環境部署 python 官網鏈接 Python Release Python 3.10.6 | Python.org 下載 Python 3.10.6 版本安裝包 下載好后雙擊 點擊安裝&#xff0c;這里需要選擇一下&#xff0c;把環境變量加上。&#xff08;這里是默認安裝到C盤…

【芯片封測學習專欄 -- 單 Die 與 多Die(Chiplet)介紹】

請閱讀【嵌入式開發學習必備專欄 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目錄 Overview單個Die&#xff08;Monolithic Die&#xff09;多個Die&#xff08;Chiplet Architecture or Heterogeneous SoC&#xff09;如何判斷一個SoC是…

Windows 安裝 Docker 和 Docker Compose

&#x1f680; 作者主頁&#xff1a; 有來技術 &#x1f525; 開源項目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 倉庫主頁&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 歡迎點贊 &#x1f44d; 收藏 ?評論 …

java_將數據存入elasticsearch進行高效搜索

使用技術簡介&#xff1a; (1) 使用Nginx實現反向代理&#xff0c;使前端可以調用多個微服務 (2) 使用nacos將多個服務管理關聯起來 (3) 將數據存入elasticsearch進行高效搜索 (4) 使用消息隊列rabbitmq進行消息的傳遞 (5) 使用 openfeign 進行多個服務之間的api調用 參…

Github Copilot學習筆記

&#xff08;一&#xff09;Prompt Engineering 利用AI工具生成prompt設計好的prompt結構使用MarkDown語法&#xff0c;按Role, Skills, Constrains, Background, Requirements和Demo這幾個維度描述需求。然后收輸入提示詞&#xff1a;作為 [Role], 擁有 [Skills], 嚴格遵守 […

android分區和root

線刷包內容&#xff1a; 線刷包是一個完整的android鏡像&#xff0c;不但包括android、linux和用戶數據&#xff0c;還包括recovery等。當然此圖中沒有recovery,但是我們可以自己刷入一個。 主要分區 system.img 系統分區&#xff0c;包括linux下主要的二進制程序。 boot.img…