This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-showcase.git
The following commit(s) were added to refs/heads/main by this push:
new cb76fe4 Update Python agent to v1.2.0 with forking support and PVM
metrics (#228)
cb76fe4 is described below
commit cb76fe4b6bfbf946ea6d827ae6129433fcd7a3a1
Author: chani <[email protected]>
AuthorDate: Mon Jan 19 20:07:58 2026 +0900
Update Python agent to v1.2.0 with forking support and PVM metrics (#228)
---
services/recommendation-service/Dockerfile | 38 ++++++-------
services/recommendation-service/requirements.txt | 17 ++++++
services/recommendation-service/src/app.py | 69 ++++++++++++------------
3 files changed, 68 insertions(+), 56 deletions(-)
diff --git a/services/recommendation-service/Dockerfile
b/services/recommendation-service/Dockerfile
index 40f36fa..ba69280 100644
--- a/services/recommendation-service/Dockerfile
+++ b/services/recommendation-service/Dockerfile
@@ -1,30 +1,26 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
#
-
# @feature: python-agent;
-FROM apache/skywalking-python:0.7.0-grpc-py3.9
+FROM apache/skywalking-python:1.2.0-grpc-py3.10-slim
WORKDIR /workspace
-
COPY requirements.txt .
-
RUN pip install -r requirements.txt
-
COPY src .
-
-CMD python app.py
+# Enable forking support with -p flag for gunicorn workers
+# PVM meter reporter is enabled by default in v1.0.0+
+CMD ["run", "-p", "gunicorn", "-w", "2", "-b", "0.0.0.0:80", "app:app"]
diff --git a/services/recommendation-service/requirements.txt
b/services/recommendation-service/requirements.txt
index 3a4df99..57f62f5 100644
--- a/services/recommendation-service/requirements.txt
+++ b/services/recommendation-service/requirements.txt
@@ -1,2 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
Flask==2.3.2
requests==2.26.0
+gunicorn==21.2.0
diff --git a/services/recommendation-service/src/app.py
b/services/recommendation-service/src/app.py
index f43df06..250bbc3 100644
--- a/services/recommendation-service/src/app.py
+++ b/services/recommendation-service/src/app.py
@@ -17,50 +17,49 @@
import os
import requests
+from flask import Flask, jsonify, request
-if __name__ == '__main__':
- from flask import Flask, jsonify, request
-
- app = Flask(__name__)
+app = Flask(__name__)
- @app.route('/health', methods=['GET'])
- def health():
- return 'OK'
[email protected]('/health', methods=['GET'])
+def health():
+ return 'OK'
- @app.route('/rcmd', methods=['GET'])
- def application():
- headers = {}
- for key in [
- 'x-b3-traceid',
- 'x-b3-spanid',
- 'x-b3-parentspanid',
- 'x-b3-sampled',
- 'x-b3-flags',
- ]:
- val = request.headers.get(key)
- if val is not None:
- headers[key] = request.headers[key]
[email protected]('/rcmd', methods=['GET'])
+def application():
+ headers = {}
+ for key in [
+ 'x-b3-traceid',
+ 'x-b3-spanid',
+ 'x-b3-parentspanid',
+ 'x-b3-sampled',
+ 'x-b3-flags',
+ ]:
+ val = request.headers.get(key)
+ if val is not None:
+ headers[key] = request.headers[key]
- songsResponse = requests.get('http://songs/songs', headers=headers)
- songs = songsResponse.json()
- ratingResponse = requests.get('http://rating/rating', headers=headers)
- ratings = ratingResponse.json()
+ songsResponse = requests.get('http://songs/songs', headers=headers)
+ songs = songsResponse.json()
+ ratingResponse = requests.get('http://rating/rating', headers=headers)
+ ratings = ratingResponse.json()
- # combine ratings to songs
- ratings_dict = {}
- for rating_data in ratings:
- song_id = rating_data['id']
- ratings_dict[song_id] = rating_data['rating']
- for song_data in songs:
- song_id = song_data['id']
- rating = ratings_dict.get(song_id)
- if rating is not None:
- song_data['rating'] = rating
+ # combine ratings to songs
+ ratings_dict = {}
+ for rating_data in ratings:
+ song_id = rating_data['id']
+ ratings_dict[song_id] = rating_data['rating']
+ for song_data in songs:
+ song_id = song_data['id']
+ rating = ratings_dict.get(song_id)
+ if rating is not None:
+ song_data['rating'] = rating
- return jsonify(songs)
+ return jsonify(songs)
+if __name__ == '__main__':
PORT = os.getenv('PORT', 80)
app.run(host='0.0.0.0', port=PORT)