From 74a05a99ae10080c36516c9be5414a5c306cc692 Mon Sep 17 00:00:00 2001 From: Anton Kolesnikov Date: Fri, 13 Dec 2024 19:05:09 +0800 Subject: [PATCH] chore(examples): update python examples (#3769) * chore(examples): update python examples * update python docs * fix * Update examples/language-sdk-instrumentation/python/simple/README.md Co-authored-by: Christian Simon * Update examples/language-sdk-instrumentation/python/rideshare/django/README.md Co-authored-by: Christian Simon * update doc links * update screenshots and links --------- Co-authored-by: Christian Simon --- .../configure-client/language-sdks/python.md | 4 +- .../python/README.md | 73 +++++---- .../python/README_zh.md | 6 +- .../python/rideshare/README.md | 138 ------------------ .../python/rideshare/README_zh.md | 110 -------------- .../python/rideshare/django/.env.dev | 2 +- .../python/rideshare/django/README.md | 23 +-- .../django/app/hello_django/settings.py | 8 +- .../rideshare/django/docker-compose.yml | 24 ++- .../python/rideshare/django/load-generator.py | 9 +- .../python/rideshare/fastapi/README.md | 8 +- .../python/rideshare/flask/README.md | 6 +- .../python/rideshare/flask/lib/server.py | 2 +- .../python/simple/README.md | 16 ++ 14 files changed, 121 insertions(+), 308 deletions(-) delete mode 100644 examples/language-sdk-instrumentation/python/rideshare/README.md delete mode 100644 examples/language-sdk-instrumentation/python/rideshare/README_zh.md create mode 100644 examples/language-sdk-instrumentation/python/simple/README.md diff --git a/docs/sources/configure-client/language-sdks/python.md b/docs/sources/configure-client/language-sdks/python.md index 3118e331e4..3088354907 100644 --- a/docs/sources/configure-client/language-sdks/python.md +++ b/docs/sources/configure-client/language-sdks/python.md @@ -98,5 +98,5 @@ If your Pyroscope server has multi-tenancy enabled, you'll need to configure a t ## Python profiling examples Check out the following resources to learn more about Python profiling: -- [Python examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/language-sdk-instrumentation/python) -- [Python demo](https://play.grafana.org/a/grafana-pyroscope-app/single?query=process_cpu%3Asamples%3Acount%3A%3Amilliseconds%7Bservice_name%3D%22pyroscope-rideshare-python%22%7D&from=now-1h&until=now) showing Python example with tags +- [Python examples](https://github.com/pyroscope-io/pyroscope/tree/main/examples/language-sdk-instrumentation/python) demonstrating how Django, Flask, and FastAPI apps can be profiled with Pyroscope. +- A [Python demo](https://play.grafana.org/a/grafana-pyroscope-app/profiles-explorer?searchText=&panelType=time-series&layout=grid&hideNoData=off&explorationType=flame-graph&var-serviceName=pyroscope-rideshare-python&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds&var-dataSource=grafanacloud-profiles) on play.grafana.org. diff --git a/examples/language-sdk-instrumentation/python/README.md b/examples/language-sdk-instrumentation/python/README.md index 44e6ed25fc..983fb3f562 100644 --- a/examples/language-sdk-instrumentation/python/README.md +++ b/examples/language-sdk-instrumentation/python/README.md @@ -1,42 +1,57 @@ ## Continuous Profiling for Python applications + ### Profiling a Python Rideshare App with Pyroscope -![python_example_architecture_05_00](https://user-images.githubusercontent.com/23323466/135728737-0c5e54ca-1e78-4c6d-933c-145f441c96a9.gif) + +![python_example_architecture_new_00](https://user-images.githubusercontent.com/23323466/173369382-267af200-6126-4bd0-8607-a933e8400dbb.gif) #### _Read this in other languages._ + [简体中文](README_zh.md) -Note: For documentation on the Pyroscope pip package visit [our website](https://pyroscope.io/docs/python/) +Note: For documentation on the Pyroscope pip package visit [our website](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/python/) + +## Live Demo + +Feel free to check out the [live demo](https://play.grafana.org/a/grafana-pyroscope-app/profiles-explorer?searchText=&panelType=time-series&layout=grid&hideNoData=off&explorationType=flame-graph&var-serviceName=pyroscope-rideshare-python&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds&var-dataSource=grafanacloud-profiles) of this example on our demo page. + ## Background + In this example we show a simplified, basic use case of Pyroscope. We simulate a "ride share" company which has three endpoints found in `server.py`: + - `/bike` : calls the `order_bike(search_radius)` function to order a bike - `/car` : calls the `order_car(search_radius)` function to order a car - `/scooter` : calls the `order_scooter(search_radius)` function to order a scooter -We also simulate running 3 distinct servers in 3 different regions (via [docker-compose.yml](https://github.com/pyroscope-io/pyroscope/blob/main/examples/python/docker-compose.yml)) +We also simulate running 3 distinct servers in 3 different regions: + - us-east - eu-north - ap-south One of the most useful capabilities of Pyroscope is the ability to tag your data in a way that is meaningful to you. In this case, we have two natural divisions, and so we "tag" our data to represent those: + - `region`: statically tags the region of the server running the code - `vehicle`: dynamically tags the endpoint (similar to how one might tag a controller rails) - ## Tagging static region + Tagging something static, like the `region`, can be done in the initialization code in the `config.tags` variable: -``` + +```python pyroscope.configure( application_name = "ride-sharing-app", - server_address = "http://pyroscope:4040", - tags = { + server_address = "http://pyroscope:4040", + tags = { "region": f'{os.getenv("REGION")}', # Tags the region based off the environment variable } ) ``` ## Tagging dynamically within functions + Tagging something more dynamically, like we do for the `vehicle` tag can be done inside our utility `find_nearest_vehicle()` function using a `with pyroscope.tag_wrapper()` block -``` + +```python def find_nearest_vehicle(n, vehicle): with pyroscope.tag_wrapper({ "vehicle": vehicle}): i = 0 @@ -46,58 +61,63 @@ def find_nearest_vehicle(n, vehicle): ``` What this block does, is: + 1. Add the tag `{ "vehicle" => "car" }` 2. execute the `find_nearest_vehicle()` function 3. Before the block ends it will (behind the scenes) remove the `{ "vehicle" => "car" }` from the application since that block is complete ## Resulting flame graph / performance results from the example + ### Running the example -To run the example run the following commands: -``` + +Try out one of the Django, Flask, or FastAPI examples located in the `rideshare` directory by running the following commands: + +```shell # Pull latest pyroscope and grafana images: docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest # Run the example project: -docker-compose up --build +docker compose up --build # Reset the database (if needed): -# docker-compose down +docker compose down ``` -What this example will do is run all the code mentioned above and also send some mock-load to the 3 servers as well as their respective 3 endpoints. If you select our application: `ride-sharing-app.cpu` from the dropdown, you should see a flame graph that looks like this (below). After we give 20-30 seconds for the flame graph to update and then click the refresh button we see our 3 functions at the bottom of the flame graph taking CPU resources _proportional to the size_ of their respective `search_radius` parameters. +What this example will do is run all the code mentioned above and also send some mock-load to the 3 servers as well as their respective 3 endpoints. If you select our application: `ride-sharing-app` from the dropdown, you should see a flame graph that looks like this (below). After we give 20-30 seconds for the flame graph to update and then click the refresh button we see our 3 functions at the bottom of the flame graph taking CPU resources _proportional to the size_ of their respective `search_radius` parameters. ## Where's the performance bottleneck? -![python_first_slide_05](https://user-images.githubusercontent.com/23323466/135881284-c75a5b65-6151-44fb-a459-c1f9559cb51a.jpg) + +![python_slide_1](https://github.com/user-attachments/assets/1d38ddbf-2a9e-4f07-8d70-343cff878307) The first step when analyzing a profile outputted from your application, is to take note of the _largest node_ which is where your application is spending the most resources. In this case, it happens to be the `order_car` function. -The benefit of using the Pyroscope package, is that now that we can investigate further as to _why_ the `order_car()` function is problematic. Tagging both `region` and `vehicle` allows us to test two good hypotheses: +The benefit of using the Pyroscope package, is that now that we can investigate further as to _why_ the `order_car` function is problematic. Tagging both `region` and `vehicle` allows us to test two good hypotheses: - Something is wrong with the `/car` endpoint code - Something is wrong with one of our regions -To analyze this we can select one or more tags from the "Select Tag" dropdown: +To analyze this we can select one or more labels on the "Labels" page: -![image](https://user-images.githubusercontent.com/23323466/135525308-b81e87b0-6ffb-4ef0-a6bf-3338483d0fc4.png) +![python_slide_2](https://github.com/user-attachments/assets/5a8ee6ed-d2e1-42f3-98f3-d977adfccd08) -## Narrowing in on the Issue Using Tags -Knowing there is an issue with the `order_car()` function we automatically select that tag. Then, after inspecting multiple `region` tags, it becomes clear by looking at the timeline that there is an issue with the `eu-north` region, where it alternates between high-cpu times and low-cpu times. +## Narrowing in on the Issue Using Labels -We can also see that the `mutex_lock()` function is consuming almost 70% of CPU resources during this time period. -![python_second_slide_05](https://user-images.githubusercontent.com/23323466/135805908-ae9a1650-51fc-457a-8c47-0b56e8538b08.jpg) +Knowing there is an issue with the `order_car` function we automatically select that tag. Then, after inspecting multiple `region` tags, it becomes clear by looking at the timeline that there is an issue with the `eu-north` region, where it alternates between high-cpu times and low-cpu times. -## Comparing two time periods -Using Pyroscope's "comparison view" we can actually select two different time ranges from the timeline to compare the resulting flame graphs. The pink section on the left timeline results in the left flame graph, and the blue section on the right represents the right flame graph. +We can also see that the `find_nearest_vehicle` function is consuming almost 70% of CPU resources during this time period. -When we select a period of low-cpu utilization and a period of high-cpu utilization we can see that there is clearly different behavior in the `mutex_lock()` function where it takes **51% of CPU** during low-cpu times and **78% of CPU** during high-cpu times. -![python_third_slide_05](https://user-images.githubusercontent.com/23323466/135805969-55fdee40-fe0c-412d-9ec0-0bbc6a748ed4.jpg) +![python_slide_3](https://github.com/user-attachments/assets/57614064-bced-4363-bdba-b028c132e1e9) ## Visualizing diff between two flame graphs + While the difference _in this case_ is stark enough to see in the comparison view, sometimes the diff between the two flame graphs is better visualized with them overlayed over each other. Without changing any parameters, we can simply select the diff view tab and see the difference represented in a color-coded diff flame graph. -![python_fourth_slide_05](https://user-images.githubusercontent.com/23323466/135805986-594ffa3b-e735-4f91-875d-4f76fdff2b60.jpg) + +![python_slide_4](https://github.com/user-attachments/assets/9c89458f-f7fb-4561-80a2-6a86c7c2ed4c) ### More use cases + We have been beta testing this feature with several different companies and some of the ways that we've seen companies tag their performance data: +- Linking profiles with trace data - Tagging controllers - Tagging regions - Tagging jobs from a redis / sidekiq / rabbitmq queue @@ -107,6 +127,7 @@ We have been beta testing this feature with several different companies and some - Etc... ### Future Roadmap + We would love for you to try out this example and see what ways you can adapt this to your python application. Continuous profiling has become an increasingly popular tool for the monitoring and debugging of performance issues (arguably the fourth pillar of observability). We'd love to continue to improve this pip package by adding things like integrations with popular tools, memory profiling, etc. and we would love to hear what features _you would like to see_. diff --git a/examples/language-sdk-instrumentation/python/README_zh.md b/examples/language-sdk-instrumentation/python/README_zh.md index 76839e8fd4..db0bfc8ddb 100644 --- a/examples/language-sdk-instrumentation/python/README_zh.md +++ b/examples/language-sdk-instrumentation/python/README_zh.md @@ -1,10 +1,10 @@ ### Pyroscope Rideshare 示例 -![python_example_architecture_05_00](https://user-images.githubusercontent.com/23323466/135728737-0c5e54ca-1e78-4c6d-933c-145f441c96a9.gif) +![python_example_architecture_new_00](https://user-images.githubusercontent.com/23323466/173369382-267af200-6126-4bd0-8607-a933e8400dbb.gif) #### _用其他语言阅读此文。_ [English](README.md) -注意:关于Pyroscope pip包的文档,请访问[我们的网站](https://pyroscope.io/docs/python/) +注意:关于Pyroscope pip包的文档,请访问[我们的网站](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/python/) ## 背景介绍 在这个例子中,我们展示了 Pyroscope 的一个简化的基本用例。我们模拟了一个 "骑行共享" 公司,它有三个请求端点,可以在`server.py`中找到: @@ -53,7 +53,7 @@ def find_nearest_vehicle(n, vehicle): ### 运行这个例子 要运行该例子,请运行以下命令: ``` -# 拉取最新的 pyroscope/grafana 镜像: +# 拉取最新的 pyroscope/pyroscope 镜像: docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest diff --git a/examples/language-sdk-instrumentation/python/rideshare/README.md b/examples/language-sdk-instrumentation/python/rideshare/README.md deleted file mode 100644 index e4c94d1efc..0000000000 --- a/examples/language-sdk-instrumentation/python/rideshare/README.md +++ /dev/null @@ -1,138 +0,0 @@ -## Continuous Profiling for Python applications - -### Profiling a Python Rideshare App with Pyroscope - -![python_example_architecture_new_00](https://user-images.githubusercontent.com/23323466/173369382-267af200-6126-4bd0-8607-a933e8400dbb.gif) - -#### _Read this in other languages._ - -[简体中文](README_zh.md) - -Note: For documentation on the Pyroscope pip package visit [our website](https://pyroscope.io/docs/python/) - -## Background - -In this example we show a simplified, basic use case of Pyroscope. We simulate a "ride share" company which has three endpoints found in `server.py`: - -- `/bike` : calls the `order_bike(search_radius)` function to order a bike -- `/car` : calls the `order_car(search_radius)` function to order a car -- `/scooter` : calls the `order_scooter(search_radius)` function to order a scooter - -We also simulate running 3 distinct servers in 3 different regions (via [docker-compose.yml](https://github.com/pyroscope-io/pyroscope/blob/main/examples/python/docker-compose.yml)) - -- us-east -- eu-north -- ap-south - -One of the most useful capabilities of Pyroscope is the ability to tag your data in a way that is meaningful to you. In this case, we have two natural divisions, and so we "tag" our data to represent those: - -- `region`: statically tags the region of the server running the code -- `vehicle`: dynamically tags the endpoint (similar to how one might tag a controller rails) - -## Tagging static region - -Tagging something static, like the `region`, can be done in the initialization code in the `config.tags` variable: - -```python -pyroscope.configure( - application_name = "ride-sharing-app", - server_address = "http://pyroscope:4040", - tags = { - "region": f'{os.getenv("REGION")}', # Tags the region based off the environment variable - } -) -``` - -## Tagging dynamically within functions - -Tagging something more dynamically, like we do for the `vehicle` tag can be done inside our utility `find_nearest_vehicle()` function using a `with pyroscope.tag_wrapper()` block - -```python -def find_nearest_vehicle(n, vehicle): - with pyroscope.tag_wrapper({ "vehicle": vehicle}): - i = 0 - start_time = time.time() - while time.time() - start_time < n: - i += 1 -``` - -What this block does, is: - -1. Add the tag `{ "vehicle" => "car" }` -2. execute the `find_nearest_vehicle()` function -3. Before the block ends it will (behind the scenes) remove the `{ "vehicle" => "car" }` from the application since that block is complete - -## Resulting flame graph / performance results from the example - -### Running the example - -To run the example run the following commands: - -```shell -# Pull latest pyroscope and grafana images: -docker pull grafana/pyroscope:latest -docker pull grafana/grafana:latest - -# Run the example project: -docker-compose up --build - -# Reset the database (if needed): -# docker-compose down -``` - -What this example will do is run all the code mentioned above and also send some mock-load to the 3 servers as well as their respective 3 endpoints. If you select our application: `ride-sharing-app.cpu` from the dropdown, you should see a flame graph that looks like this (below). After we give 20-30 seconds for the flame graph to update and then click the refresh button we see our 3 functions at the bottom of the flame graph taking CPU resources _proportional to the size_ of their respective `search_radius` parameters. - -## Where's the performance bottleneck? - -Profiling is most effective for applications that contain tags. The first step when analyzing performance from your application, is to use the Tag Explorer page in order to determine if any tags are consuming more resources than others. - -![vehicle_tag_breakdown](https://user-images.githubusercontent.com/23323466/191306637-a601f463-a247-4588-a285-639424a08b87.png) - -![image](https://user-images.githubusercontent.com/23323466/191319887-8fff2605-dc74-48ba-b0b7-918e3c95ed91.png) - -The benefit of using Pyroscope, is that by tagging both `region` and `vehicle` and looking at the Tag Explorer page we can hypothesize: - -- Something is wrong with the `/car` endpoint code where `car` vehicle tag is consuming **68% of CPU** -- Something is wrong with one of our regions where `eu-north` region tag is consuming **54% of CPU** - -From the flame graph we can see that for the `eu-north` tag the biggest performance impact comes from the `find_nearest_vehicle()` function which consumes close to **68% of cpu**. To analyze this we can go directly to the comparison page using the comparison dropdown. - -## Comparing two time periods - -Using Pyroscope's "comparison view" we can actually select two different queries and compare the resulting flame graphs: -- Left flame graph: `{ region != "eu-north", ... }` -- Right flame graph: `{ region = "eu-north", ... }` - -When we select a period of low-cpu utilization and a period of high-cpu utilization we can see that there is clearly different behavior in the `find_nearest_vehicle()` function where it takes: -- Left flame graph: **22% of CPU** when `{ region != "eu-north", ... }` -- right flame graph: **82% of CPU** when `{ region = "eu-north", ... }` - -![python_pop_out_library_comparison_00](https://user-images.githubusercontent.com/23323466/191374975-d374db02-4cb1-48d5-bc1a-6194193a9f09.png) - -## Visualizing diff between two flame graphs - -While the difference _in this case_ is stark enough to see in the comparison view, sometimes the diff between the two flame graphs is better visualized with them overlayed over each other. Without changing any parameters, we can simply select the diff view tab and see the difference represented in a color-coded diff flame graph. -![find_nearest_vehicle_diff](https://user-images.githubusercontent.com/23323466/191320888-b49eb7de-06d5-4e6b-b9ac-198d7c9e2fcf.png) - - -### More use cases - -We have been beta testing this feature with several different companies and some of the ways that we've seen companies tag their performance data: -- Linking profiles with trace data -- Tagging controllers -- Tagging regions -- Tagging jobs from a redis / sidekiq / rabbitmq queue -- Tagging commits -- Tagging staging / production environments -- Tagging different parts of their testing suites -- Etc... - -### Live Demo - -Feel free to check out the [live demo](https://demo.pyroscope.io/explore?query=rideshare-app-python.cpu%7B%7D&groupBy=region&groupByValue=All) of this example on our demo page. - -### Future Roadmap - -We would love for you to try out this example and see what ways you can adapt this to your python application. Continuous profiling has become an increasingly popular tool for the monitoring and debugging of performance issues (arguably the fourth pillar of observability). - -We'd love to continue to improve this pip package by adding things like integrations with popular tools, memory profiling, etc. and we would love to hear what features _you would like to see_. diff --git a/examples/language-sdk-instrumentation/python/rideshare/README_zh.md b/examples/language-sdk-instrumentation/python/rideshare/README_zh.md deleted file mode 100644 index 2fe6bbc8e2..0000000000 --- a/examples/language-sdk-instrumentation/python/rideshare/README_zh.md +++ /dev/null @@ -1,110 +0,0 @@ -### Pyroscope Rideshare 示例 -![python_example_architecture_new_00](https://user-images.githubusercontent.com/23323466/173369382-267af200-6126-4bd0-8607-a933e8400dbb.gif) - -#### _用其他语言阅读此文。_ -[English](README.md) - -注意:关于Pyroscope pip包的文档,请访问[我们的网站](https://pyroscope.io/docs/python/) -## 背景介绍 - -在这个例子中,我们展示了 Pyroscope 的一个简化的基本用例。我们模拟了一个 "骑行共享" 公司,它有三个请求端点,可以在`server.py`中找到: -- `/bike`:调用`order_bike(search_radius)`函数来订购共享自行车 -- `/car` : 调用`order_car(search_radius)`函数来订购共享汽车 -- `/scooter` : 调用`order_scooter(search_radius)`函数来订购共享摩托车 - -我们还模拟了在3个不同地区运行3个不同的服务器(通过[docker-compose.yml](https://github.com/pyroscope-io/pyroscope/blob/main/examples/python/docker-compose.yml)) -- us-east -- eu-north -- ap-south - - -Pyroscope最有用的功能之一是能够以对你有意义的方式来标记你的数据。在这种情况下,我们有两个自然划分,因此我们 "标记(tag)" 我们的数据以表示这些: -- `region`:静态地标记运行代码的服务器的区域 -- `vehicle`: 动态标记端点(类似于标记控制器轨道的方式) - -## 标记静态区域 -标记一些静态的东西,如`reigon`,可以在初始化代码中的`config.tags`变量中完成: -``` -pyroscope.configure( - app_name = "ride-sharing-app", - server_address = "http://pyroscope:4040", - tags = { - "region": f'{os.getenv("REGION")}', # 根据环境变量标记该区域 - } -) -``` - -## 在函数中动态地添加标签 -像我们对 `vehicle` 标签所做的那样,可以在我们的实用程序 `find_nearest_vehicle()` 函数中使用 `with pyroscope.tag_wrapper()` 上下文区块来完成更动态的标记 -``` -def find_nearest_vehicle(n, vehicle): - with pyroscope.tag_wrapper({ "vehicle": vehicle}): - i = 0 - start_time = time.time() - while time.time() - start_time < n: - i += 1 -``` -这个上下文区块的作用是: -1. 添加标签 `{ "vehicle" => "car" }` -2. 执行`find_nearest_vehicle()`函数 -3. 在该块结束之前,它将(在后台)从应用程序中删除`{ "vehicle" => "car" }`,因为该上下文区块已经完成 - -## 例子中产生的火焰图/性能结果 -### 运行这个例子 -要运行该例子,请运行以下命令: -``` -# 拉取最新的 pyroscope/pyroscope 镜像: -docker pull grafana/pyroscope:latest -docker pull grafana/grafana:latest - -# 运行示例项目: -docker-compose up --build - -# 重置数据库(非必需): -# docker-compose down -``` - - -这个例子要做的是运行上面提到的所有代码,同时向3个服务器以及它们各自的3个端点发送一些模拟负载。如果你从下拉菜单中选择我们的应用程序:`rid-sharing-app.cpu`,你应该看到一个看起来像这样的火焰图(见下文)。在我们给予20-30秒的时间来更新火焰图之后,点击刷新按钮,我们看到火焰图底部的3个函数占用的CPU资源与它们各自的`search_radius`参数 _大小成正比_。 -## 性能瓶颈在哪里? -![python_first_slide_05](https://user-images.githubusercontent.com/23323466/135881284-c75a5b65-6151-44fb-a459-c1f9559cb51a.jpg) - -当分析从你的应用程序输出的剖析文件时,第一步是注意 _最大的节点_,这是你的应用程序花费最多资源的地方。在这个例子中,它恰好是 `order_car` 函数。 - -使用 Pyroscope 包的好处是,现在我们可以进一步调查为什么 `order_car()` 函数有问题。同时标记 `region`和 `vehicle`使我们能够测试两个好的假设: -- `/car` 端点的代码出了问题 -- 我们的一个区域出了问题 - -为了分析这一点,我们可以从 "Select Tag" 下拉菜单中选择一个或多个标签: - -![image](https://user-images.githubusercontent.com/23323466/135525308-b81e87b0-6ffb-4ef0-a6bf-3338483d0fc4.png) - -## 使用标签缩小问题的范围 -知道`order_car()`函数有问题,我们就自动选择该标签。然后,在检查了多个 `region` 标签后,通过查看时间线,可以清楚地看到 `eu-north`区域存在问题,它在高cpu时间和低cpu时间之间交替出现。 - -我们还可以看到,`mutex_lock()`函数在这段时间内几乎消耗了70%的CPU资源。 -![python_second_slide_05](https://user-images.githubusercontent.com/23323466/135805908-ae9a1650-51fc-457a-8c47-0b56e8538b08.jpg) - -## 比较两个时间段的情况 -使用 Pyroscope 的 "比较视图",我们实际上可以从时间线上选择两个不同的时间范围来比较所产生的火焰图。左边时间线上的粉红色部分结果是左边的火焰图,右边的蓝色部分代表右边的火焰图。 -当我们选择一个低CPU利用率的时期和一个高CPU利用率的时期时,我们可以看到`mutex_lock()`函数有明显不同的行为,它在低CPU时期占用**51%的CPU**,在高CPU时期占用**78%的CPU**。 -![python_third_slide_05](https://user-images.githubusercontent.com/23323466/135805969-55fdee40-fe0c-412d-9ec0-0bbc6a748ed4.jpg) - -## 可视化两个火焰图之间的差异 -虽然在 _这个例子_ 中,差异足以在比较视图中看到,但有时两个火焰图之间的差异在相互叠加的情况下会更直观。在不改变任何参数的情况下,我们可以简单地选择差异视图选项卡,看到用彩色编码的差异火焰图表示的差异。 -![python_fourth_slide_05](https://user-images.githubusercontent.com/23323466/135805986-594ffa3b-e735-4f91-875d-4f76fdff2b60.jpg) - -### 更多用例 -我们一直在与几个不同的公司测试这一功能,我们看到一些公司标记其业务数据的方式: -- 标记控制器 -- 标记区域 -- 从redis / sidekiq / rabbitmq队列中标记作业 -- 标记提交 -- 标记预发/生产环境 -- 标记其测试套件的不同部分 -- 等等... - -### 未来路线图 -我们希望你能尝试一下这个例子,看看你能用什么方式来适配你的 python 应用。持续剖析已经成为监测和调试性能问题的一个越来越流行的工具(可以说是可观察性的第四个支柱)。 - -我们希望通过增加与流行工具的集成、内存分析等内容来继续改进这个pip包,我们很想听听 _你希望看到的功能_。 diff --git a/examples/language-sdk-instrumentation/python/rideshare/django/.env.dev b/examples/language-sdk-instrumentation/python/rideshare/django/.env.dev index b5d6844cdc..1d27496e4f 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/django/.env.dev +++ b/examples/language-sdk-instrumentation/python/rideshare/django/.env.dev @@ -1,6 +1,6 @@ DEBUG=1 SECRET_KEY=foo -DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] web +DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] eu-north us-east ap-south SQL_ENGINE=django.db.backends.postgresql SQL_DATABASE=hello_django_dev SQL_USER=hello_django diff --git a/examples/language-sdk-instrumentation/python/rideshare/django/README.md b/examples/language-sdk-instrumentation/python/rideshare/django/README.md index 2e18c81b66..9086f63236 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/django/README.md +++ b/examples/language-sdk-instrumentation/python/rideshare/django/README.md @@ -1,15 +1,16 @@ -# Dockerizing Django with Pyroscope, Postgres, Gunicorn, and Nginx -This is a simple rideshare example that adds Pyroscope to a Django application and uses it to profile various routes +# Django Example -### Development -Uses the default Django development server. +To run the example run the following commands: +``` +# Pull latest pyroscope and grafana images: +docker pull grafana/pyroscope:latest +docker pull grafana/grafana:latest -1. Rename *.env.dev-sample* to *.env.dev*. -1. Update the environment variables in the *docker-compose.yml* and *.env.dev* files. -1. Build the images and run the containers: +# Run the example project: +docker compose up --build - ```sh - $ docker-compose up -d --build - ``` +# Reset the database (if needed): +docker compose down +``` - Test it out at [http://localhost:8000](http://localhost:8000). The "app" folder is mounted into the container and your code changes apply automatically. +Navigate to [Grafana](http://localhost:3000/a/grafana-pyroscope-app/profiles-explorer?explorationType=flame-graph&var-serviceName=ride-sharing-app&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds) to Explore Profiles. diff --git a/examples/language-sdk-instrumentation/python/rideshare/django/app/hello_django/settings.py b/examples/language-sdk-instrumentation/python/rideshare/django/app/hello_django/settings.py index 85babbf47a..ec256f203e 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/django/app/hello_django/settings.py +++ b/examples/language-sdk-instrumentation/python/rideshare/django/app/hello_django/settings.py @@ -138,7 +138,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -app_name = os.getenv("PYROSCOPE_APPLICATION_NAME", "django-ride-sharing-app") +app_name = os.getenv("PYROSCOPE_APPLICATION_NAME", "ride-sharing-app") server_addr = os.getenv("PYROSCOPE_SERVER_ADDRESS", "http://pyroscope:4040") basic_auth_username = os.getenv("PYROSCOPE_BASIC_AUTH_USER", "") basic_auth_password = os.getenv("PYROSCOPE_BASIC_AUTH_PASSWORD", "") @@ -148,7 +148,7 @@ server_address = server_addr, basic_auth_username = basic_auth_username, basic_auth_password = basic_auth_password, - # tags = { - # "region": f'{os.getenv("REGION")}', - # } + tags = { + "region": f'{os.getenv("REGION")}', + } ) diff --git a/examples/language-sdk-instrumentation/python/rideshare/django/docker-compose.yml b/examples/language-sdk-instrumentation/python/rideshare/django/docker-compose.yml index 02dca8acbe..d95e002e67 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/django/docker-compose.yml +++ b/examples/language-sdk-instrumentation/python/rideshare/django/docker-compose.yml @@ -3,13 +3,31 @@ services: image: grafana/pyroscope ports: - 4040:4040 - web: + us-east: + build: ./app + command: python manage.py runserver 0.0.0.0:8000 + env_file: + - ./.env.dev + environment: + - REGION=us-east + depends_on: + - db + eu-north: + build: ./app + command: python manage.py runserver 0.0.0.0:8000 + env_file: + - ./.env.dev + environment: + - REGION=eu-north + depends_on: + - db + ap-south: build: ./app command: python manage.py runserver 0.0.0.0:8000 - ports: - - 8000:8000 env_file: - ./.env.dev + environment: + - REGION=ap-south depends_on: - db db: diff --git a/examples/language-sdk-instrumentation/python/rideshare/django/load-generator.py b/examples/language-sdk-instrumentation/python/rideshare/django/load-generator.py index bcdaf92945..c399d92942 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/django/load-generator.py +++ b/examples/language-sdk-instrumentation/python/rideshare/django/load-generator.py @@ -3,7 +3,9 @@ import time HOSTS = [ - 'web', + 'us-east', + 'eu-north', + 'ap-south', ] VEHICLES = [ @@ -14,8 +16,7 @@ if __name__ == "__main__": print(f"starting load generator") - time.sleep(15) - print('done sleeping') + time.sleep(3) while True: host = HOSTS[random.randint(0, len(HOSTS) - 1)] vehicle = VEHICLES[random.randint(0, len(VEHICLES) - 1)] @@ -27,4 +28,4 @@ except BaseException as e: print (f"http error {e}") - time.sleep(random.uniform(0.2, 0.4)) + time.sleep(random.uniform(0.1, 0.2)) diff --git a/examples/language-sdk-instrumentation/python/rideshare/fastapi/README.md b/examples/language-sdk-instrumentation/python/rideshare/fastapi/README.md index f1f32d3089..193d839aeb 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/fastapi/README.md +++ b/examples/language-sdk-instrumentation/python/rideshare/fastapi/README.md @@ -1,4 +1,4 @@ -## Fastapi Example +## FastAPI Example To run the example run the following commands: ``` @@ -7,8 +7,10 @@ docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest # Run the example project: -docker-compose up --build +docker compose up --build # Reset the database (if needed): -# docker-compose down +docker compose down ``` + +Navigate to [Grafana](http://localhost:3000/a/grafana-pyroscope-app/profiles-explorer?explorationType=flame-graph&var-serviceName=ride-sharing-app&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds) to Explore Profiles. diff --git a/examples/language-sdk-instrumentation/python/rideshare/flask/README.md b/examples/language-sdk-instrumentation/python/rideshare/flask/README.md index 6431ea2aae..84fa59044a 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/flask/README.md +++ b/examples/language-sdk-instrumentation/python/rideshare/flask/README.md @@ -7,8 +7,10 @@ docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest # Run the example project: -docker-compose up --build +docker compose up --build # Reset the database (if needed): -# docker-compose down +docker compose down ``` + +Navigate to [Grafana](http://localhost:3000/a/grafana-pyroscope-app/profiles-explorer?explorationType=flame-graph&var-serviceName=ride-sharing-app&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds) to Explore Profiles. diff --git a/examples/language-sdk-instrumentation/python/rideshare/flask/lib/server.py b/examples/language-sdk-instrumentation/python/rideshare/flask/lib/server.py index 27ab2b7393..518148805a 100644 --- a/examples/language-sdk-instrumentation/python/rideshare/flask/lib/server.py +++ b/examples/language-sdk-instrumentation/python/rideshare/flask/lib/server.py @@ -22,7 +22,7 @@ # Sets the global default tracer provider trace.set_tracer_provider(provider) -app_name = os.getenv("PYROSCOPE_APPLICATION_NAME", "flask-ride-sharing-app") +app_name = os.getenv("PYROSCOPE_APPLICATION_NAME", "ride-sharing-app") server_addr = os.getenv("PYROSCOPE_SERVER_ADDRESS", "http://pyroscope:4040") basic_auth_username = os.getenv("PYROSCOPE_BASIC_AUTH_USER", "") basic_auth_password = os.getenv("PYROSCOPE_BASIC_AUTH_PASSWORD", "") diff --git a/examples/language-sdk-instrumentation/python/simple/README.md b/examples/language-sdk-instrumentation/python/simple/README.md new file mode 100644 index 0000000000..15a80c8da2 --- /dev/null +++ b/examples/language-sdk-instrumentation/python/simple/README.md @@ -0,0 +1,16 @@ +## Basic Example + +To run the example run the following commands: +``` +# Pull latest pyroscope and grafana images: +docker pull grafana/pyroscope:latest +docker pull grafana/grafana:latest + +# Run the example project: +docker compose up --build + +# Reset the database (if needed): +docker compose down +``` + +Navigate to [Grafana](http://localhost:3000/a/grafana-pyroscope-app/profiles-explorer?explorationType=flame-graph&var-serviceName=simple.python.app&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds) to Explore Profiles.